package io.ouka.jvm.hotspot.selfread.methodinvoke;

import io.ouka.jvm.hotspot.selfread.constant.BasicType;
import io.ouka.jvm.hotspot.selfread.constant.ByteCodes;
import io.ouka.jvm.hotspot.selfread.constant.ConstantPoolConstants;
import io.ouka.jvm.hotspot.selfread.domain.Code;
import io.ouka.jvm.hotspot.selfread.domain.MethodInfo;

import java.lang.reflect.Field;

/**
 * @author ouka
 * BytecodeInterpreter
 */
//执行器
public class BytecodeInterpreter {
    public static void run(JavaThread javaThread, MethodInfo methodInfo) {
        Code codes = methodInfo.getCodeAttributes()[1].getCodes();
//        codes.get

        JavaVFrame frame = (JavaVFrame) javaThread.getStack().peek();

        int c;
        while (!(codes.getIndex()>=codes.getLength())){
            c =  codes.getU1Code();

            switch (c){
                case ByteCodes.GETSTATIC: {
                    System.out.println("执行指令: GETSTATIC");
                    //TODO 获取常量池里面的静态属性 后面就是操作数（常量池索引）
                    short u1Code = codes.getUnsignedShort();
                    String classNameByFieldInfo = methodInfo.getInstanceKlass().getConstantPool().getClassNameByFieldInfo(u1Code);
                    String fieldName = methodInfo.getInstanceKlass().getConstantPool().getFieldName(u1Code);

                    try {
                        Class<?> clazz = Class.forName(classNameByFieldInfo.replace('/', '.'));
                        Field field = clazz.getField(fieldName);
                        frame.getStack().push(new StackValue(BasicType.T_OBJECT, field.get(null)));
                    } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
                case ByteCodes.LDC:{
                    //TODO LDC  后面一般都有操作数的
                    System.out.println("执行指令: LDC");

                    int operand = codes.getU1Code();
                    int i = methodInfo.getInstanceKlass().getConstantPool().getTag()[operand-1];
                    switch (i){
                        case ConstantPoolConstants.JVM_CONSTANT_Float:
                            break;
                        case ConstantPoolConstants.JVM_CONSTANT_String:
                            int index = (int) methodInfo.getInstanceKlass().getConstantPool().getDataMap().get(operand);

                            String content = (String) methodInfo.getInstanceKlass().getConstantPool().getDataMap().get(index);

                            frame.getStack().push(new StackValue(BasicType.T_OBJECT, content));

                            break;
                        case ConstantPoolConstants.JVM_CONSTANT_Class:
                            break;
                        default:
                            throw new IllegalArgumentException("未知类型");
                    }

                    break;}
                case ByteCodes.INVOKEVIRTUAL:{
                    //TODO INVOKEVIRTUAL 一样有操作数
                    System.out.println("执行指令: INVOKEVIRTUAL");
                    //
                    short operand = codes.getUnsignedShort();
                    // 获取类名、方法名、方法描述符
                    String className = methodInfo.getInstanceKlass().getConstantPool().getClassNameByFieldInfo(operand);
                    String methodName = methodInfo.getInstanceKlass().getConstantPool().getMethodNameByMethodInfo(operand);
                    String descriptorName = methodInfo.getInstanceKlass().getConstantPool().getDescriptorNameByMethodInfo(operand);
                    if (className.startsWith("java")) {

                    }


                    break;}
                case ByteCodes.RETURN:
                    break;

                default:
                    throw new IllegalArgumentException("暂时不支持");

            }

        }

    }
}
